package nveces.jspwiki.plugins.pdf;

import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.COLON;
import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.COLON_DOUBLE_SLASH;
import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.CONTENT_TYPE_PDF;
import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.DEFAULT_XSL_FILE;
import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.EMPTY;
import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.HEADER_CACHE_CONTROL;
import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.HEADER_PRAGMA;
import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.HEADER_PRIVATE;
import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.KEY_ILLEGALARGUMENT_PAGE;
import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.PARAM_ENCODING;
import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.PARAM_PAGE;
import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.PARAM_XSL;
import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.PDF_BUNDLE;
import static nveces.jspwiki.plugins.pdf.MagicNamesPluginPdf.SLASH;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import com.ecyrd.jspwiki.WikiContext;
import com.ecyrd.jspwiki.WikiEngine;
import com.ecyrd.jspwiki.WikiPage;

public class Wiki2PdfServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;
    protected Logger          log              = Logger.getLogger(this.getClass().getName());
    protected WikiEngine      wikiEngine;
    private Html2Pdf          html2Pdf;

    public void init(final ServletConfig config) throws ServletException {
        super.init(config);
        this.wikiEngine = WikiEngine.getInstance(config);
        this.html2Pdf = new Html2Pdf();
    }

    public void doGet(final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        response.setHeader(HEADER_CACHE_CONTROL, HEADER_PRIVATE);
        response.setHeader(HEADER_PRAGMA, HEADER_PRIVATE);
        //
        String page = request.getParameter(PARAM_PAGE);
        if ((page == null) || (EMPTY.equals(page.toString()))) {
            throw new IllegalArgumentException(this.getMessage(request, KEY_ILLEGALARGUMENT_PAGE));
        }
        WikiContext context = new WikiContext(wikiEngine, request, new WikiPage(wikiEngine, page));
        if (!context.hasAccess(response, true)) {
            return;
        }
        String xsl = request.getParameter(PARAM_XSL);
        if ((xsl == null) || ("".equals(xsl.trim()))) {
            xsl = DEFAULT_XSL_FILE;
        }
        // Get encoding or use the default if the parameter is empty
        String encoding = request.getParameter(PARAM_ENCODING);
        if (encoding == null || ("".equals(encoding.trim()))) {
            encoding = response.getCharacterEncoding();
        }
        encoding = encoding.trim();
        ByteArrayOutputStream out = null;
        try {
            out = this.html2Pdf.createPDF(page, this.createHtml(page), xsl, getBaseURL(request), response, encoding);
            // Prepare response
            response.setContentType(CONTENT_TYPE_PDF);
            response.setContentLength(out.size());
            // Send content to Browser
            response.getOutputStream().write(out.toByteArray());
            response.getOutputStream().flush();

        } catch (Throwable t) {
            log.error("doGet()-->Throwable caught while trying to generate PDF.", t);
            throw new ServletException(t);
        }
    }

    private String createHtml(String page) {
        return this.wikiEngine.getHTML(page);
    }

    private static String getBaseURL(HttpServletRequest request) {
        return request.getScheme().concat(COLON_DOUBLE_SLASH).concat(request.getServerName()).concat(COLON).concat(
                String.valueOf(request.getServerPort())).concat(request.getContextPath()).concat(SLASH);
    }

    private String getMessage(HttpServletRequest request, String key) {
        return this.wikiEngine.getInternationalizationManager().get(PDF_BUNDLE, request.getLocale(), key);
    }
}
